Skip to content

Support renv profiles#1296

Open
jonkeane wants to merge 4 commits intomainfrom
1122_renv_location
Open

Support renv profiles#1296
jonkeane wants to merge 4 commits intomainfrom
1122_renv_location

Conversation

@jonkeane
Copy link
Contributor

@jonkeane jonkeane commented Mar 4, 2026

Support renv profiles and custom renv file locations specified with the RENV_PATHS_LOCKFILE environment variable

Fixes #1122

resolved <- renv::paths$lockfile(project = bundleDir)

# If the resolved file exists, and is different from the standard location,
# copy it to the standard location.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to copy it at all? Why can't we use it where it lives? It's a little odd to me that this function would alter the contents of the current working directory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that's confusing about this is that it's actually not copying it into the working directory, but actually into the temporary directory the rsconnect creates and copies files over to a temporary directory

bundleDir <- bundleAppDir(
appDir = appDir,
appFiles = appFiles,
appMode = appMetadata$appMode
)
defer(unlink(bundleDir, recursive = TRUE))
which calls

rsconnect/R/bundle.R

Lines 1 to 12 in c704931

# Given a path to an directory and a list of files in that directory, copies
# those files to a new temporary directory. Performs some small modifications
# in this process, including renaming single-file Shiny apps to "app.R" and
# stripping packrat and renv commands from .Rprofile. Returns the path to the
# temporary directory.
bundleAppDir <- function(
appDir,
appFiles,
appPrimaryDoc = NULL,
appMode = NULL,
verbose = FALSE
) {

But thinking about this more, we might need to make sure that we can handle relative paths in RENV_PATHS_LOCKFILE since when this is run inside of the temp bundle dir, those might not work (e.g. if RENV_PATHS_LOCKFILE="../renv.lock" and the app is at /home/jonkeane/Documents/myapp/subdir/, my lock file is at /home/jonkeane/Documents/myapp/renv.lock we don't want the target of this copy to be /tmp/.../renv.lock

if (file.exists(standard)) {
cli::cli_warn(c(
"Using lockfile at {.path {resolved}} instead of {.path {standard}}.",
i = "The lockfile in the project root may be outdated.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I run this function twice, I'm going to get this warning, even though the files themselves are identical. Should we be checking the contents of the files instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add checking the contents, but running user-exported commands in rsconnect, this path should not alter someone's app directory (so this shouldn't happen in practice unless someone calls rsconnect:::ensureRenvLockFile (or the other internal functions that always operate on the temp bundle dir

@jonkeane jonkeane requested review from karawoo and removed request for dskard March 10, 2026 21:25
@jonkeane
Copy link
Contributor Author

Ok, this is ready for another look. Thanks for the comments, @nealrichardson those nudged me to take a different approach that I think is much cleaner (even if the copying wasn't as big of a deal as it seemed), since we don't actually need the lockfile in the bundle, now we more directly parse it in-situ. One small negative side effect of this is that we will not include a lock file that happens to be outside of the directory tree in the bundle even if it exists (and could in principle be added to the bundle). But that's a bit of a weird edgecase to support anyway.

The TL;DR of this recent change is that I've made it so that parseRenvDependencies() takes a path to the lockfile rather than a directory.

@jonkeane
Copy link
Contributor Author

Oh, and additionally some of the oddities around relative renv.lock file paths: rstudio/renv#2238

Copy link
Contributor

@karawoo karawoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need to make removeRenv aware of other potential lockfile locations

unlink(renvLockFile(path))

renv::snapshot(bundleDir, packages = deps$Package, prompt = FALSE)
# renv::snapshot() respects RENV_PATHS_LOCKFILE and renv profiles, so the
# lockfile may have been written to a non-standard location.
lockfile <- resolveRenvLockFile(bundleDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be good to have some error handling here in case something goes wrong with resolving the lockfile, otherwise we're likely to get cryptic errors from parseRenvDependencies

Suggested change
lockfile <- resolveRenvLockFile(bundleDir)
lockfile <- resolveRenvLockFile(bundleDir)
if (is.null(lockfile)) {
cli::cli_abort("renv::snapshot() did not produce a lockfile")
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Deployment fails with lock file in custom location

3 participants